package org.swift.mashup.wsdl;

import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.StringReader;
import java.util.Set;
import java.util.logging.Logger;

import javax.xml.namespace.QName;
import javax.xml.soap.SOAPMessage;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;

import org.apache.commons.io.IOUtils;

public class LoggingMessageHandler implements SOAPHandler<SOAPMessageContext> {

	private final static Logger log = Logger.getLogger("org.swift.mashup.wsdl.LoggingMessageHandler");
	
	@Override
	public Set<QName> getHeaders() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void close(MessageContext arg0) {
		// TODO Auto-generated method stub

	}

	private boolean processMessage(SOAPMessageContext context) {
		Boolean outboundProperty = (Boolean) context
				.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);

		if (outboundProperty) {
			log.info("\nOutbound message:");
		} else {
			log.info("\nInbound message:");
		}
		SOAPMessage message = context.getMessage();
		
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
			message.writeTo(baos);
		} catch (Exception e) {
			log.warning("could not log message");
		} 
        
        baos.toByteArray();
        
        Source source = new StreamSource(new StringReader(baos.toString()));
		// Process Payload Source
		printSource(source, outboundProperty);
		// ....

		// If the payload is modified, Do lm.setPayload(source) to be safe,
		// Without it, behavior may vary on the kind of source returned in
		// lm.getPayload().
		// See LogicalMessage JavaDoc for more details.
		// lm.setPayload(modifiedPayload);
		return false;

	}

	private static void printSource(Source payload, Boolean outbound) {
		try {
			TransformerFactory factory = TransformerFactory.newInstance();
			Transformer transformer = factory.newTransformer();
			transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION,
					"yes");
			transformer.setOutputProperty(OutputKeys.METHOD, "xml");
			transformer.setOutputProperty(OutputKeys.INDENT, "yes");
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			Result result = new StreamResult(out);
			transformer.transform(payload, result);
			
			log.info(out.toString());
			if (outbound) {
			FileOutputStream file;
				try {
					file = new FileOutputStream("c:/remisrequest.txt");
					IOUtils.write(out.toString(), file);
					file.close();			
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
		} catch (TransformerException e) {
			e.printStackTrace();
		}
	}

	@Override
	public boolean handleFault(SOAPMessageContext context) {
		processMessage(context);
		return true;
	}

	@Override
	public boolean handleMessage(SOAPMessageContext context) {
		processMessage(context);
		return true;
	}

}
